// *********************************************************************************
// Project Name : zkx2024
// Author       : Jlan
// Email        : 15533610762@163.com
// Create Time  : 2024-05-16
// File Name    : .v
// Module Name  :
// Called By    :
// Abstract     :
//
// 
// *********************************************************************************
// Modification History:
// Date         By              Version                 Change Description
// -----------------------------------------------------------------------
// 2024-05-16    Macro           1.0                     Original
//  
// *********************************************************************************

module  rd_addr_gen(
    input   [0:0]               CLK,
    input   [0:0]               RST_N,
    input   [7:0]               READY,
    input   [0:0]               QOS_SEL_I,
    output  logic   [0:0]       RD_FIX_EN_O,
    output  logic   [12:0]      RD_FIX_ADDR_O,
    input   logic   [35:0]      RD_FIX_DATA_I,
    raddr_st_bus.raddr          ra_st,
    rdaddr_srammux_bus.raddr   ra_smux,
    rd_bus.master               ra_tx
//    rd_fix_bus.rdaddr           ra_fix
);
//-------parameter------------------------------//
parameter   FIX_SRAM_ADDR    =   4'h0;
//----------------------------------------------//
//-----------inter singnal define---------------//
//-----rd_fsm_define
typedef enum    {
        IDLE,
        WAIT_ADDR,
        JUMP,
        READ_SOP,
        READ_EOP
    }rd_st_t;
rd_st_t rd_st_c,rd_st_n,rd_st_c_d;
//-----ready signal-------
logic   [7:0]   sp_ready;
logic   [7:0]   wrr_req;
logic   [0:0]   wrr_next;
logic   [7:0]   wrr_grant;
logic   [7:0]   wrr_ready;
//------------------------
//logic   [0:0]   frist_sop;
logic   [17:0]  frist_addr;
logic   [17:0]  gen_addr;
logic   [8:0]   data_size;
logic   [8:0]   fix_cnt;
logic   [8:0]   share_cnt;
logic   [8:0]   tx_cnt;
logic   [8:0]   tx_cnt_d;
logic   [0:0]   now_fix;
logic   [0:0]   rd_vld_d;
logic   [0:0]   fix_vld_d;
//----------------------------------------------//
//-------inst arbritor--------------------------//
strict_priority sp(
    .CLK(CLK),
    .RST_N(RST_N),
    .READY0(READY[7]),
    .READY0(READY[6]),
    .READY0(READY[5]),
    .READY0(READY[4]),
    .READY0(READY[3]),
    .READY0(READY[2]),
    .READY0(READY[1]),
    .READY0(READY[0]),
    .READY_OUT(sp_ready)
);

assign  wrr_req = {READY[0],
                   READY[1],
                   READY[2],
                   READY[3],
                   READY[4],
                   READY[5],
                   READY[6],
                   READY[7]};

assign  wrr_next = ra_tx.RD_EOP || ra_st.PRIORITY_JMP;

assign  wrr_ready={wrr_grant[0],
                   wrr_grant[1],
                   wrr_grant[2],
                   wrr_grant[3],
                   wrr_grant[4],
                   wrr_grant[5],
                   wrr_grant[6],
                   wrr_grant[7]};
wrr_arbiter wrr(
    .CLK(CLK),
    .RST_N(RST_N),
    .REQ(wrr_req),
    .NEXT(wrr_next),
    .GRANT(wrr_grant)
);

assign  ra_st.READY =   QOS_SEL_I? wrr_ready: sp_ready;
//-------inst arbritor--------------------------//
//-------rd_fsm---------------------------------//
always_ff@(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        rd_st_c <=  IDLE;
        rd_st_c_d <= IDLE;
    end
    else begin
        rd_st_c <=  rd_st_n;
        rd_st_c_d <= rd_st_c;
    end
end

always_comb begin
    rd_st_n = rd_st_c;
    case(rd_st_c)
        IDLE:begin
            if(|ra_st.READY)
                rd_st_n =   WAIT_ADDR;
            else
                rd_st_n =   IDLE;
        end
        WAIT_ADDR:begin
            if(ra_st.PRIORITY_JMP)
                rd_st_n =   JUMP;
            else if(ra_st.RD_VLD)
                rd_st_n =   READ_SOP;
            else
                rd_st_n =   WAIT_ADDR;
        end
        JUMP:begin
                rd_st_n =   IDLE;
        end
        READ_SOP:begin
            if(ra_st.FLUSH_START)
                rd_st_n =   WAIT_ADDR;
            else if(ra_tx.RD_EOP)
                rd_st_n =   READ_EOP;
            else
                rd_st_n =   READ_SOP;
        end
        READ_EOP:begin
                rd_st_n =   IDLE;
        end
        default:begin
                rd_st_n =   IDLE;
        end
    endcase
end
//----------------------------------------------//
//----generate addr logic-----------------------//
//assign  frist_sop   = (rd_st_c_d == WAIT_ADDR)&&(rd_st_c == RD_SOP);
//assign  frist_addr  = ra_st.RD_VLD ? ra_st.DATA_ADDR: '0;
always_ff @(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        frist_addr  <=   '0;
        data_size   <=   '0;
    end
    else if(ra_st.RD_VLD)begin
        frist_addr  <=  ra_st.DATA_ADDR;
        data_size   <=  (ra_st.DATA_SIZE[1:0]== 2'b00) ?
                            (ra_st.DATA_SIZE[9:2]):
                            ((ra_st.DATA_SIZE[9:2]) + 1'b1);
    end
    else if(rd_st_c== READ_EOP)
        frist_addr  <= '0;
end

always_ff @(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        rd_vld_d    <= '0;
    end
    else
        rd_vld_d    <=  ra_st.RD_VLD;
end
assign  now_fix =   frist_addr[17:13] == FIX_SRAM_ADDR;
always_ff @(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        fix_cnt    <= '0;
    end
    else if(fix_cnt == (data_size-1'b1))
        fix_cnt    <= '0;
    else if(ra_st.FLUSH_START)
        fix_cnt    <= '0;
    else if(rd_st_c == READ_SOP)
        fix_cnt    <= fix_cnt + 1'b1;
end
always_ff @(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        share_cnt    <= '0;
    end
    else if(share_cnt == (data_size-1'b1))
        share_cnt    <= '0;
    else if(ra_st.FLUSH_START)
        share_cnt    <= '0;
    else if(rd_st_c == READ_SOP && ra_smux.RD_EN)
        share_cnt    <= share_cnt + 1'b1;
end
always_ff @(posedge CLK or negedge RST_N)begin:share_addr
    if(!RST_N)begin
        ra_smux.RD_EN   <= '0;
        ra_smux.RD_ADDR <= '0;
    end
    else if(rd_vld_d && !now_fix)begin
        ra_smux.RD_EN   <= 1'b1;
        ra_smux.RD_ADDR <= frist_addr;
    end
    else if(rd_st_c == READ_SOP && ra_smux.RD_DATA_VLD)begin
        ra_smux.RD_EN   <= 1'b1;
        ra_smux.RD_ADDR[9:0] <= ra_smux.RD_ADDR[9:0] + share_cnt;
    end
    else
        ra_smux.RD_EN   <= 1'b0;
end
always_ff @(posedge CLK or negedge RST_N)begin:fix_addr
    if(!RST_N)begin
        RD_FIX_EN_O   <= '0;
        RD_FIX_ADDR_O <= '0;
    end
    else if(rd_vld_d && now_fix)begin
        RD_FIX_EN_O   <= 1'b1;
        RD_FIX_ADDR_O <= frist_addr;
    end
    else if(rd_st_c == READ_SOP)begin
        RD_FIX_EN_O   <= 1'b1;
        RD_FIX_ADDR_O[9:0] <= RD_FIX_ADDR_O[9:0] + fix_cnt;
    end
    else 
        RD_FIX_EN_O   <= '0;
end

always_ff @(posedge CLK or negedge RST_N)begin:fix_addr_gen
    if(!RST_N)begin
        fix_vld_d   <= '0;
    end
    else
        fix_vld_d   <= RD_FIX_EN_O;
end
//send data to tx ------------------------------//
always_ff@(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        ra_tx.RD_SOP    <= '0;
    end
    else if(ra_st.RD_VLD)
        ra_tx.RD_SOP    <= 1'b1;
    else
        ra_tx.RD_SOP    <= '0;
end
always_ff@(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        ra_tx.RD_VLD  <= '0;
        ra_tx.RD_DATA <= '0;
    end
    else if((rd_st_c==READ_SOP)&& now_fix && fix_vld_d)begin
        ra_tx.RD_VLD  <= 1'b1;
        ra_tx.RD_DATA <= RD_FIX_DATA_I;
    end
    else if((rd_st_c==READ_SOP)&& !now_fix && ra_smux.RD_DATA_VLD)begin
        ra_tx.RD_VLD  <= 1'b1;
        ra_tx.RD_DATA <= ra_smux.RD_DATA;
    end
    else
        ra_tx.RD_VLD  <= '0;
end
always_ff@(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        tx_cnt        <= '0;
    end
    else if(tx_cnt == (data_size-1'b1))
        tx_cnt        <= '0;
    else if(ra_st.FLUSH_START)
        tx_cnt        <= '0;
    else if((rd_st_c==READ_SOP)&& now_fix && fix_vld_d)begin
        tx_cnt        <= tx_cnt + 1'b1;
    end
    else if((rd_st_c==READ_SOP)&& !now_fix && ra_smux.RD_DATA_VLD)begin
        tx_cnt        <= tx_cnt + 1'b1;
    end
end
always_ff @(posedge CLK or negedge RST_N) begin
    if(!RST_N)
        tx_cnt_d    <= '0;
    else
        tx_cnt_d    <= tx_cnt;
end 
always_ff @(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
        ra_tx.RD_EOP <= '0;
    end
    else if(now_fix && !fix_vld_d &&(tx_cnt_d == (data_size -1'b1)))
        ra_tx.RD_EOP <= 1'b1;
    else
        ra_tx.RD_EOP <= 1'b0;
end
always_ff @(posedge CLK or negedge RST_N) begin
    if(!RST_N)begin
        ra_st.FLUSH_END <= '0;
    end
    else
        ra_st.FLUSH_END <= ra_st.FLUSH_START;
end 
always_ff @(posedge CLK or negedge RST_N) begin
    if(!RST_N)begin
        ra_st.RD_STATE_VLD  <= '0;
        ra_st.RD_STATE      <= '0;
    end
    else if(ra_tx.RD_SOP)begin
        ra_st.RD_STATE_VLD  <= 1'b1;
        ra_st.RD_STATE      <= 2'b01;
    end
    else if(ra_tx.RD_EOP)begin
        ra_st.RD_STATE_VLD  <= 1'b1;
        ra_st.RD_STATE      <= 2'b11;
    end
    else if(!ra_tx.RD_SOP && rd_st_c==READ_SOP)begin
        ra_st.RD_STATE_VLD  <= 1'b1;
        ra_st.RD_STATE      <= 2'b10;
    end
    else begin
        ra_st.RD_STATE_VLD  <= 1'b1;
        ra_st.RD_STATE      <= 2'b00;
    end
end 

//----------------------------------------------//
endmodule

